#pragma once
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;
__device__ const float PI = 3.1415926f;

class Complex {
public:
    float real;
    float imag;

    // Wn
    __device__ static Complex W(int n) {
        Complex res(cos(2.0 * PI / n), sin(2.0 * PI / n));
        return res;
    }

    // Wn^k
    __device__ static Complex W(int n, int k) {
        Complex res(cos(2.0 * PI * k / n), sin(2.0 * PI * k / n));
        return res;
    }

    Complex() {

    }

    // Complex operator+=(const Complex &other) const {
    //     return GetComplex(this->real + other.real, this->imag + other.imag);
    // }

    static Complex SumTwoComplex(Complex a,Complex b) {
        Complex r;
        r.real = a.real + b.real;
        r.imag = a.imag + b.imag;
        return r;
    }

    static Complex GetComplex(float real, float imag) {
        Complex r;
        r.real = real;
        r.imag = imag;
        return r;
    }

    static Complex GetRandomComplex() {
        Complex r;
        r.real = (float)rand() / rand();
        r.imag = (float)rand() / rand();
        return r;
    }

    static Complex GetRandomReal() {
        Complex r;
        r.real = (float)rand() / rand();
        r.imag = 0;
        return r;
    }

    static Complex GetRandomReal(int real) {
        Complex r;
        r.real = real;
        r.imag = 0;
        return r;
    }

    static Complex GetRandomPureImag() {
        Complex r;
        r.real = 0;
        r.imag = (float)rand() / rand();
        return r;
    }


    static float GetPureRealFromComplex(Complex complex){
         return complex.real;
    }


    static bool Equals(Complex one, Complex other) {


       return one.real - other.real <= 1 && one.imag - other.imag <= 1 ;

        // return one.real == other.real && one.imag == other.imag;
    }

    static string ToString (Complex complex){
        return  std::to_string(complex.real) + "+"  + std::to_string(complex.imag) + "i";
    }


    __device__ Complex(float real, float imag) {
        this->real = real;
        this->imag = imag;
    }

    __device__ void operator+=(const Complex &other) {
        this->real += other.real;
        this->imag += other.imag;
    }
    __device__ Complex operator+(const Complex &other) {
        Complex res(this->real + other.real, this->imag + other.imag);
        return res;
    }

    __device__ Complex operator-(const Complex &other) {
        Complex res(this->real - other.real, this->imag - other.imag);
        return res;
    }

    __device__ Complex operator*(const Complex &other) {
        Complex res(this->real * other.real - this->imag * other.imag, this->imag * other.real + this->real * other.imag);
        return res;
    }

    
};